#include <iostream>
#include <upnp.h>
#include <upnptools.h>
#include <string.h>

#include "ControlPoint.h"
/*
#include "DeviceList.h"
#include "MediaServer.h"
#include "MediaRenderer.h"
#include "WDNas.h"
#include "ChromecastDevice.h"
*/
using namespace std;
/*
DeviceList *devices = NULL;
int upnpControlHandle = -1;
pthread_t timerThread;

char *getFirstDocumentItem(IXML_Document *doc, const char *item)
{
	IXML_NodeList *nodeList = NULL;
	IXML_Node *textNode = NULL;
	IXML_Node *tmpNode = NULL;
	char *ret = NULL;

	nodeList = ixmlDocument_getElementsByTagName(doc, (char *)item);
	if (nodeList) {
		tmpNode = ixmlNodeList_item(nodeList, 0);
		if (tmpNode) {
			textNode = ixmlNode_getFirstChild(tmpNode);
			if (!textNode) {
				ret = strdup("");
				goto epilogue;
			}
			ret = strdup(ixmlNode_getNodeValue(textNode));
			if (!ret) {
				ret = strdup("");
			}
		}
	}

epilogue:
	if (nodeList)
		ixmlNodeList_free(nodeList);

	return ret;
}

int addDevice(IXML_Document *descDoc, const char *location, int expires)
{
	int i = 0;
	int ret = 0;
	Device *device = NULL;

	devices->lockList();
	char *type = getFirstDocumentItem(descDoc, "deviceType");

	if (strcmp(type, "urn:schemas-upnp-org:device:MediaServer:1") == 0) {
		device = new MediaServer();
	} else if (strcmp(type, "urn:schemas-upnp-org:device:MediaRenderer:1") == 0) {
		device = new MediaRenderer();
	} else if (strcmp(type, "urn:schemas-wd-com:device:WdNAS-DEV_0064:1") == 0) {
		device = new WDNas();
	} else if (strcmp(type, "urn:dial-multiscreen-org:device:dial:1") == 0) {
		device = new ChromecastDevice();
	} else {
		cout << "Unhandled Type: " << type << endl;
		devices->unlockList();
		return 0;
	}
	device->setUDN(getFirstDocumentItem(descDoc, "UDN"));
	device->setFriendlyName(getFirstDocumentItem(descDoc, "friendlyName"));

	char *baseURL = getFirstDocumentItem(descDoc, "URLBase");
	char *relURL = getFirstDocumentItem(descDoc, "presentationURL");
	char presURL[200];

	ret = UpnpResolveURL((baseURL ? baseURL : location), relURL, presURL);
	if (UPNP_E_SUCCESS != ret) {
		//cerr << "Error generating pres_url" << endl;
		devices->unlockList();
		return ret;
	}
	
	device->setPresURL(presURL);

	if (!devices->contains(device)) {
		devices->addDevice(device);
	}
	devices->unlockList();

	return 0;
}

int searchCB(Upnp_EventType type, void *event, void *clientd)
{
	int ret;

	switch (type) {
		case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
		case UPNP_DISCOVERY_SEARCH_RESULT:
			struct Upnp_Discovery *discEvent = (struct Upnp_Discovery *)event;
			IXML_Document *descDoc = NULL;

			if (discEvent->ErrCode != UPNP_E_SUCCESS) {
				cerr << "Error in Discovery Callback: " << discEvent->ErrCode << endl;
				return 0;
			}
		
			ret = UpnpDownloadXmlDoc(discEvent->Location, &descDoc);
			if (ret != UPNP_E_SUCCESS) {
				cerr << "Error obtaining device description from " << discEvent->Location << endl;
				return ret;
			} else {
				addDevice(descDoc, discEvent->Location, discEvent->Expires);
			}

			if (discEvent) {
				ixmlDocument_free(descDoc);
			}
			break;
	}

	return 0;
}

void *timerLoop(void *args)
{
	while (1)
		sleep(1000);
}

int gatherUPNPDevices()
{
	int rc;
	char *ipAddress = NULL;
	int port = 0;

	devices = new DeviceList();	
	
	rc = UpnpInit(ipAddress, port);	
	if (rc != UPNP_E_SUCCESS) {
		cerr << "UPnp initialization error" << endl;
		UpnpFinish();
		return rc;
	}

	if (!ipAddress) {
		ipAddress = UpnpGetServerIpAddress();
	}
	if (!port) {
		port = UpnpGetServerPort();
	}

	cout << "UPnP Initialized... IP Address: " << ipAddress << " Port: " << port << endl;

	rc = UpnpRegisterClient(searchCB, &upnpControlHandle, &upnpControlHandle);
	rc = pthread_create(&timerThread, NULL, timerLoop, NULL);
	rc = UpnpSearchAsync(upnpControlHandle, 5, "ssdp:all", NULL);

	pthread_exit(NULL);
	
	delete devices;

	return rc;
}
*/
int main(int argc, char **argv)
{
	ControlPoint *cp = new ControlPoint();
	cp->start();
	//return gatherUPNPDevices();
	return 0;
}
